home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 April: Mac OS SDK / Dev.CD Apr 96 SDK / Dev.CD Apr 96 SDK1.toast / Development Kits (Disc 1) / OpenDoc Development Framework / ODFDev / ODF / Framewrk / FWPart / Sources / FWLink.cpp < prev    next >
Encoding:
Text File  |  1995-11-08  |  11.9 KB  |  400 lines  |  [TEXT/MPS ]

  1. //========================================================================================
  2. //
  3. //    File:                FWLink.cpp
  4. //    Release Version:    $ 1.0d11 $
  5. //
  6. //    Copyright:    © 1995 by Apple Computer, Inc., all rights reserved.
  7. //
  8. //========================================================================================
  9.  
  10. #include "FWFrameW.hpp"
  11.  
  12. #ifndef FWLINK_H
  13. #include "FWLink.h"
  14. #endif
  15.  
  16. // ----- Framework Includes -----
  17.  
  18. #ifndef FWPART_H
  19. #include "FWPart.h"
  20. #endif
  21.  
  22. #ifndef FWPRESEN_H
  23. #include "FWPresen.h"
  24. #endif
  25.  
  26. #ifndef FWITERS_H
  27. #include "FWIters.h"
  28. #endif
  29.  
  30. // ----- Foundation Includes -----
  31.  
  32. #ifndef FWPRIDEB_H
  33. #include "FWPriDeb.h"
  34. #endif
  35.  
  36. // ----- OpenDoc Includes -----
  37.  
  38. #ifndef SOM_Module_OpenDoc_StdProps_defined
  39. #include <StdProps.xh>
  40. #endif
  41.  
  42. #ifndef SOM_Module_OpenDoc_StdTypes_defined
  43. #include <StdTypes.xh>
  44. #endif
  45.  
  46. #ifndef SOM_ODStorageUnit_xh
  47. #include <StorageU.xh>
  48. #endif
  49.  
  50. #ifndef SOM_ODSession_xh
  51. #include <ODSessn.xh>
  52. #endif
  53.  
  54. #ifndef SOM_ODLink_xh
  55. #include <Link.xh>
  56. #endif
  57.  
  58. #ifndef SOM_ODLinkSpec_xh
  59. #include <LinkSpec.xh>
  60. #endif
  61.  
  62. #ifndef SOM_ODLinkSource_xh
  63. #include <LinkSrc.xh>
  64. #endif
  65.  
  66. //========================================================================================
  67. //    Runtime information
  68. //========================================================================================
  69.  
  70. #if FW_LIB_EXPORT_PRAGMAS
  71. #pragma lib_export on
  72. #endif
  73.  
  74. #ifdef FW_BUILD_MAC
  75. #pragma segment framework
  76. #endif
  77.  
  78. FW_DEFINE_CLASS_M0(FW_CPublishLink)
  79. FW_DEFINE_CLASS_M0(FW_CSubscribeLink)
  80.  
  81. //========================================================================================
  82. //    class FW_CPublishLink
  83. //========================================================================================
  84.  
  85. //---------------------------------------------------------------------------------------
  86. //    FW_CPublishLink::FW_CPublishLink
  87. //---------------------------------------------------------------------------------------
  88.  
  89. FW_CPublishLink::FW_CPublishLink(Environment* ev, 
  90.                                  ODUpdateID updateID, 
  91.                                  FW_CPresentation* presentation)
  92. {
  93.     fODLinkSource = NULL;
  94.     fUpdateID = updateID;
  95.     fPresentation = presentation;
  96.     fPendingID = updateID;
  97.     fSelected = FALSE;
  98. }
  99.  
  100. //---------------------------------------------------------------------------------------
  101. //    FW_CPublishLink::SetODLinkSource
  102. //---------------------------------------------------------------------------------------
  103.  
  104. void FW_CPublishLink::SetODLinkSource(Environment* ev, ODLinkSource* odLinkSource)
  105. {
  106.     FW_ASSERT(odLinkSource!=NULL);
  107.     FW_ASSERT(fODLinkSource==NULL);
  108.     
  109.     fODLinkSource = odLinkSource;
  110.     odLinkSource->Acquire(ev);
  111. }
  112.  
  113. //---------------------------------------------------------------------------------------
  114. //    FW_CPublishLink::~FW_CPublishLink
  115. //---------------------------------------------------------------------------------------
  116.  
  117. FW_CPublishLink::~FW_CPublishLink()
  118. {
  119.     if (fODLinkSource)
  120.         fODLinkSource->Release(somGetGlobalEnvironment());
  121. }
  122.  
  123. //---------------------------------------------------------------------------------------
  124. //    FW_CPublishLink::ContentUpdated
  125. //---------------------------------------------------------------------------------------
  126.  
  127. void FW_CPublishLink::ContentUpdated(Environment* ev, ODUpdateID updateID,
  128.                                      FW_Boolean forceUpdate)
  129. {
  130.     fUpdateID = updateID ? updateID : fPresentation->GetPart(ev)->GetSession(ev)->UniqueUpdateID(ev);
  131.  
  132.     // Don't update unless we really have to
  133.     if (this->IsOKtoUpdate(ev, forceUpdate))
  134.     {
  135.         ODLinkKey key;
  136.         FW_VOLATILE(key);
  137.  
  138.         if (fODLinkSource->Lock(ev, 0, &key)) 
  139.         {
  140.             FW_TRY
  141.             {
  142.                 fODLinkSource->Clear(ev, fUpdateID, key);
  143.                 // Clear must be followed by GetContentStorageUnit, which writes out a new set of promises
  144.                 ODStorageUnit* linkSU = fODLinkSource->GetContentStorageUnit(ev, key);
  145.  
  146.                 ExternalizeLinkContent(ev, linkSU);
  147.  
  148.                 if (updateID != kODUnknownUpdate)
  149.                     fODLinkSource->ContentUpdated(ev, fUpdateID, key);
  150.             }
  151.             FW_CATCH_BEGIN
  152.             FW_CATCH_EVERYTHING()
  153.             {
  154.                 fODLinkSource->Unlock(ev, key);    
  155.                 FW_THROW_SAME();
  156.             }
  157.             FW_CATCH_END
  158.     
  159.             fODLinkSource->Unlock(ev, key);    
  160.         }
  161.     }
  162. }
  163.  
  164. //---------------------------------------------------------------------------------------
  165. //    FW_CPublishLink::GetPublishFormat
  166. //----------------------------------------------------------------------------------------
  167. ODValueType    FW_CPublishLink::GetPublishFormat(Environment* ev)
  168. {
  169.     // Default to the part's kind
  170.     return fPresentation->GetPart(ev)->GetPartKind(ev);
  171. }
  172.  
  173. //---------------------------------------------------------------------------------------
  174. //    FW_CPublishLink::IsOKtoUpdate
  175. //----------------------------------------------------------------------------------------
  176. FW_Boolean FW_CPublishLink::IsOKtoUpdate(Environment* ev, FW_Boolean forceUpdate)
  177. {
  178.     return (forceUpdate || fODLinkSource->IsAutoUpdate(ev));
  179. }
  180.  
  181. //---------------------------------------------------------------------------------------
  182. //    FW_CPublishLink::BreakLink
  183. //----------------------------------------------------------------------------------------
  184. void FW_CPublishLink::BreakLink(Environment* ev)
  185. {
  186.     fODLinkSource->SetSourcePart(ev, (ODStorageUnit*) kODNULL);
  187.     fUpdateID = kODUnknownUpdate;
  188. }
  189.  
  190. //---------------------------------------------------------------------------------------
  191. //    FW_CPublishLink::RestoreLink
  192. //----------------------------------------------------------------------------------------
  193. void FW_CPublishLink::RestoreLink(Environment* ev, FW_CPart* part)
  194. {
  195.     fODLinkSource->SetSourcePart(ev, part->GetStorageUnit(ev));
  196. }
  197.  
  198. //========================================================================================
  199. //    class FW_CSubscribeLink
  200. //========================================================================================
  201.  
  202. //----------------------------------------------------------------------------------------
  203. //    FW_CSubscribeLink::FW_CSubscribeLink
  204. //----------------------------------------------------------------------------------------
  205.  
  206. FW_CSubscribeLink::FW_CSubscribeLink(Environment* ev, 
  207.                                      ODLink* odLink, 
  208.                                      ODLinkInfo* linkInfo, 
  209.                                      FW_CPresentation* presentation) :
  210.     fODLink(NULL),
  211.     fPresentation(presentation),
  212.     fRegistered(FALSE),
  213.     fSelected(FALSE),
  214.     fPart(NULL),
  215.     fNeedsSubscribe(TRUE)
  216. {
  217.     if (odLink)
  218.     {
  219.         fODLink = odLink;
  220.         odLink->Acquire(ev);
  221.     }
  222.  
  223.     // Copy link info
  224.     fLinkInfo = *linkInfo;
  225. }
  226.  
  227. //----------------------------------------------------------------------------------------
  228. //    FW_CSubscribeLink::~FW_CSubscribeLink
  229. //----------------------------------------------------------------------------------------
  230.  
  231. FW_CSubscribeLink::~FW_CSubscribeLink()
  232. {
  233.     Environment* ev = somGetGlobalEnvironment();
  234.     this->Unregister(ev);
  235.     if (fODLink)
  236.         fODLink->Release(ev);
  237. }
  238.  
  239. //----------------------------------------------------------------------------------------
  240. //    FW_CSubscribeLink::HandleSubscribe
  241. //----------------------------------------------------------------------------------------
  242.  
  243. void FW_CSubscribeLink::HandleSubscribe(Environment* ev)
  244. {
  245.     this->Subscribe(ev);
  246.     fNeedsSubscribe = FALSE;
  247. }
  248.  
  249. //----------------------------------------------------------------------------------------
  250. //    FW_CSubscribeLink::LinkUpdated
  251. //----------------------------------------------------------------------------------------
  252.  
  253. void FW_CSubscribeLink::LinkUpdated(Environment* ev, ODUpdateID id)
  254. {
  255.     ODLinkKey linkKey;
  256.     FW_VOLATILE(linkKey);
  257.  
  258.     /* The following is a kludge to detect when OpenDoc throws an exception in GetContentStorageUnit.
  259.        If a cross-document link was just created, LinkUpdated gets called before the link content SU 
  260.        has received any data. In that case we want to just let the exception fall on the floor.
  261.        LinkUpdated will be called again after the link data has been written.
  262.     */
  263.     FW_Boolean linkContentsOK = FALSE;
  264.     FW_VOLATILE(linkContentsOK);
  265.  
  266.     if (fODLink->Lock(ev, 0, &linkKey))
  267.     {
  268.         FW_TRY
  269.         {
  270.             ODStorageUnit* su = fODLink->GetContentStorageUnit(ev, linkKey); /* cross-doc link will fail the 1st time */
  271.             linkContentsOK = TRUE;    /* it's safe to update */
  272.             this->DoUpdateLink(ev, su);
  273.  
  274.             // --- Update the link info ---
  275.             fLinkInfo.change = id;
  276.             fLinkInfo.changeTime = fODLink->GetChangeTime(ev);
  277.  
  278.             fODLink->Unlock(ev, linkKey);
  279.  
  280.             if (fNeedsSubscribe)    /* first update must have failed */
  281.                 this->HandleSubscribe(ev);
  282.  
  283.             // --- Propagate changes to source links maintained by the part ---
  284.             this->DoPropagateChanges(ev, id);
  285.         }
  286.         FW_CATCH_BEGIN
  287.         FW_CATCH_EVERYTHING()
  288.         {
  289.             fODLink->Unlock(ev, linkKey);    
  290.             if (linkContentsOK)    /* exception was not thrown by GetContentStorageUnit */
  291.                 FW_THROW_SAME();
  292.         }
  293.         FW_CATCH_END
  294.     }
  295. }
  296.  
  297. //----------------------------------------------------------------------------------------
  298. //    FW_CSubscribeLink::DoPropagateChanges
  299. //----------------------------------------------------------------------------------------
  300. void FW_CSubscribeLink::DoPropagateChanges(Environment* ev, ODUpdateID change)
  301. {
  302.     FW_CPresentationFrameIterator fiter(fPresentation);
  303.     FW_CFrame* frame = fiter.First();
  304.     fPresentation->GetPart(ev)->ContentUpdated(ev, frame, change);
  305.  
  306.     fPresentation->Invalidate(ev);    // force all frames to be redrawn
  307. }
  308.  
  309. //----------------------------------------------------------------------------------------
  310. //    FW_CSubscribeLink::Register
  311. //----------------------------------------------------------------------------------------
  312. void FW_CSubscribeLink::Register(Environment* ev, FW_CPart* itsPart)
  313. {
  314.     ODUpdateID linkUpdateID = fODLink->GetUpdateID(ev);
  315.     FW_Boolean needsUpdate = (fLinkInfo.change != linkUpdateID);
  316.  
  317.     if (fLinkInfo.autoUpdate)
  318.     {
  319.         //--- Register for automatic updates ---
  320.         // First determine if another subscriber with the same ODLink as ours already registered
  321.         FW_Boolean alreadyRegistered = FALSE;
  322.         FW_CPartSubscribeIterator iter(itsPart);
  323.         for (FW_CSubscribeLink* subscriber = iter.First(); iter.IsNotComplete(); subscriber = iter.Next())
  324.         {
  325.             if ((subscriber != this) && fODLink->IsEqualTo(ev, subscriber->GetODLink(ev))
  326.                 && subscriber->IsRegistered(ev))
  327.             {
  328.                 alreadyRegistered = TRUE;
  329.                 break;
  330.             }
  331.         }
  332.         if (!alreadyRegistered)
  333.         {
  334.             fODLink->RegisterDependent(ev, itsPart->GetODPart(ev), fLinkInfo.change);
  335.             // part::LinkUpdated call will be generated
  336.             needsUpdate = FALSE;
  337.         }
  338.         fRegistered = TRUE;
  339.         itsPart->GetODPart(ev)->Acquire(ev);
  340.         fPart = itsPart;    // remember which part we're registered to, so we can Unregister
  341.     }
  342.  
  343.     if (needsUpdate)    // Manually update now
  344.         this->LinkUpdated(ev, linkUpdateID);
  345. }
  346.  
  347. //----------------------------------------------------------------------------------------
  348. //    FW_CSubscribeLink::Unregister
  349. //----------------------------------------------------------------------------------------
  350. void FW_CSubscribeLink::Unregister(Environment* ev)
  351. {
  352.     if (!fRegistered) return;
  353.  
  354.     if (fLinkInfo.autoUpdate)
  355.     {
  356.         // Unregister, if this is the last automatically updated destination of the link in the part
  357.         FW_ASSERT(fPart);
  358.         short autoCount = 0;
  359.         FW_CPartSubscribeIterator iter(fPart);
  360.         for (FW_CSubscribeLink* subscriber = iter.First(); iter.IsNotComplete(); subscriber = iter.Next())
  361.         {
  362.             if (subscriber->IsAutoUpdate(ev) && fODLink->IsEqualTo(ev, subscriber->GetODLink(ev)))
  363.                 autoCount++;
  364.         }
  365.         if (autoCount == 1)    // this is the only registered link
  366.         {
  367.             fODLink->UnregisterDependent(ev, fPart->GetODPart(ev));
  368.         }
  369.     }
  370.  
  371.     if (fPart)
  372.     {
  373.         fPart->GetODPart(ev)->Release(ev);
  374.         fPart = NULL;    
  375.     }
  376.  
  377.     fRegistered = FALSE;
  378. }
  379.  
  380. //---------------------------------------------------------------------------------------
  381. //    FW_CSubscribeLink::BreakLink
  382. //----------------------------------------------------------------------------------------
  383. void FW_CSubscribeLink::BreakLink(Environment* ev)
  384. {
  385.     this->Unregister(ev);
  386.     fNeedsSubscribe = TRUE;
  387. }
  388.  
  389. //---------------------------------------------------------------------------------------
  390. //    FW_CSubscribeLink::RestoreLink
  391. //----------------------------------------------------------------------------------------
  392. void FW_CSubscribeLink::RestoreLink(Environment* ev, FW_CPart* part)
  393. {
  394.     fLinkInfo.change = kODUnknownUpdate;
  395.  
  396.     // Re-register the link if necessary
  397.     this->Register(ev, part);
  398. }
  399.  
  400.